// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({
  env: 'note-eu6kf', //'note-eu6kf',
})

// 云函数入口函数
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()
  // 简单的路由
  if (event.action && noteHelper[event.action]) {
    try {
      const result = await noteHelper[event.action](wxContext, event.data)
      return result
    } catch (e) {
      return {
        message: e.message,
        code: -1,
      }
    }
  }
  return {
    message: 'hello there! you need to provide a valid action to use note helper.',
    code: -1,
  }
}


const db = cloud.database()
const _ = db.command
const $ = db.command.aggregate
const MAX_LIMIT = 100

function getTable(isExpense) {
  if (isExpense != undefined && (isExpense === false || isExpense == 'false')) {
    return 'income'
  } else {
    return 'expense'
  }
}

function output(message = '', data = {}, code = 0) {
  return {
    code,
    message,
    data
  }
}

// Note 函数列表
const noteHelper = {
  async login(context, params) {
    const openid = context.OPENID
    const doc = await db.collection('users')
      .where({
        openid,
      }).get()
    if (doc.data.length !== 0) {
      await db.collection('users')
        .where({
          openid
        })
        .update({
          data: {
            openid,
            ...params,
            updateAt: Date.now()
          }
        })
    } else {
      await db.collection('users').add({
        data: {
          openid,
          ...params,
          createAt: Date.now(),
          updatedAt: Date.now(),
        }
      })
    }
    let data = {
      openid,
      nickName: params.nickName,
      avatarUrl: params.avatarUrl
    }
    return output('登录成功', data, 0)
  },
  async getExpenseList(context, params) {
    const table = getTable(params.isExpense)
    let whereParam = {
      openid: context.OPENID,
    }
    if (params.type != undefined && params.type.length > 0) {
      whereParam.type = db.RegExp({
        regexp: '.*' + params.type,
        options: 'i'
      })
    }
    if (params.startDt && params.startDt != '' && params.endDt && params.endDt != '') {
      whereParam.date = _.gte(params.startDt).lte(params.endDt)
    }

    // 先取出集合记录总数
    const countResult = await db.collection(table).where(whereParam).count()
    const total = countResult.total
    // 计算需分几次取
    const batchTimes = Math.ceil(total / MAX_LIMIT)
    // 承载所有读操作的 promise 的数组
    const tasks = []
    for (let i = 0; i < batchTimes; i++) {
      const promise = db.collection(table)
        .field({ _id: true, type: true, money: true, date: true })
        .where(whereParam)
        .orderBy('date', 'desc')
        .skip(i * MAX_LIMIT)
        .limit(MAX_LIMIT)
        .get()
      tasks.push(promise)
    }
    // 等待所有
    if (tasks.length > 0) {
      let allData = []
      let result = await Promise.all(tasks)
      result.forEach(item => {
        allData = allData.concat(item.data)
      })
      return {
        code: 0,
        message: "",
        data: allData
      }
    } else {
      return {
        code: 0,
        message: "暂无数据",
        data: []
      }
    }
  },
  async getExpenseListByYear(context, params) {
    const table = getTable(params.isExpense)
    const doc = await db.collection(table)
      .aggregate()
      .group({
        _id: {
          openid: '$openid',
          date: $.substr(['$date', 0, 7]),
          year: $.substr(['$date', 0, 4]),
        },
        money: $.sum('$money'),
      })
      .match({
        '_id.year': _.eq(params.year),
        '_id.openid': _.eq(context.OPENID)
      })
      .project({
        _id: 0,
        money: 1,
        date: '$_id.date'
      })
      .sort({
        date: 1
      })
      .end()
    return {
      code: 0,
      message: 'ok',
      data: doc.list,
    }
  },
  async getExpenseType(context, params) {
    const table = getTable(params.isExpense)
    const countResult = await db.collection(table)
      .aggregate()
      .match({
        openid: context.OPENID
      })
      .sortByCount('$type')
      .count('count')
      .end()

    const total = countResult.list[0].count
    const batchTimes = Math.ceil(total / MAX_LIMIT)
    // 承载所有读操作的 promise 的数组
    const tasks = []
    for (let i = 0; i < batchTimes; i++) {
      const promise = db.collection(table)
        .aggregate()
        .group({
          _id: {
            type: '$type',
            openid: '$openid'
          },
          count: $.sum(1)
        })
        .match({
          '_id.openid': context.OPENID
        })
        .project({
          _id: 0,
          type: '$_id.type',
          count: '$count'
        })
        .sort({
          count: -1
        })
        .skip(i * MAX_LIMIT)
        .limit(MAX_LIMIT)
        .end()
      tasks.push(promise)
    }
    // 等待所有
    if (tasks.length > 0) {
      let allData = []
      let result = await Promise.all(tasks)
      result.forEach(item => {
        allData = allData.concat(item.list)
      })
      return {
        code: 0,
        message: "",
        data: allData
      }
    } else {
      return {
        code: 0,
        message: "暂无数据",
        total: total,
        data: []
      }
    }

    // const doc = await db.collection(table)
    //   .aggregate()
    //   .group({
    //     _id: {
    //       type: '$type',
    //       openid: '$openid'
    //     },
    //     count: $.sum(1)
    //   })
    //   .match({
    //     '_id.openid': context.OPENID
    //   })
    //   .project({
    //     _id: 0,
    //     type: '$_id.type',
    //     count: '$count'
    //   })
    //   .sort({
    //     count: -1
    //   })
    //   .end()

    // return {
    //   code: 0,
    //   message: 'ok',
    //   data: doc.list,
    // }
  },
  async addExpense(context, params) {
    const table = getTable(params.isExpense)
    const openid = context.OPENID
    var {
      type,
      date,
      money
    } = params
    money = +money
    await db.collection(table).add({
      data: {
        openid,
        type,
        date,
        money,
        createAt: Date.now()
      }
    })
    return {
      code: 0,
      message: '添加成功',
    }
  },
  async updateExpense(context, params) {
    const table = getTable(params.isExpense)
    var {
      _id,
      type,
      money
    } = params
    money = +money
    await db.collection(table).where({
      _id: _id,
      openid: context.OPENID
    }).update({
      data: {
        type,
        money,
        createAt: Date.now()
      }
    })
    return {
      code: 0,
      message: '更新成功'
    }
  },
  async deleteExpense(context, params) {
    const table = getTable(params.isExpense)

    const doc = await db.collection(table).where({
      _id: params._id,
      openid: context.OPENID
    }).remove()
    return {
      code: 0,
      message: '删除成功'
    }
  },
}
